home *** CD-ROM | disk | FTP | other *** search
/ EuroCD 3 / EuroCD 3.iso / Programming / vbcc / ic.c < prev    next >
C/C++ Source or Header  |  1998-06-24  |  52KB  |  1,467 lines

  1. /*  $VER: vbcc (ic.c) V0.4  */
  2.  
  3. #include "vbc.h"
  4.  
  5. static char FILE_[]=__FILE__;
  6.  
  7.  
  8. int do_arith(np,struct IC *,np,struct obj *);
  9.  
  10. void gen_test(struct obj *o,int t,int branch,int label)
  11. /*  Generiert ein test o, branch label und passt auf, dass      */
  12. /*  kein TEST const generiert wird.                             */
  13. {
  14.     struct IC *new;
  15.     if(o->flags&KONST){
  16.         eval_const(&o->val,t);
  17.         if(zdeqto(vdouble,d2zd(0.0))&&zleqto(vlong,l2zl(0L))&&zuleqto(vulong,ul2zul(0UL))){
  18.             if(branch==BEQ) branch=BRA; else branch=0;
  19.         }else{
  20.             if(branch==BNE) branch=BRA; else branch=0;
  21.         }
  22.     }else{
  23.         new=mymalloc(ICS);
  24.         new->code=TEST;
  25.         new->q2.flags=new->z.flags=0;
  26.         new->typf=t;
  27.         new->q1=*o;
  28.         add_IC(new);
  29.     }
  30.     if(branch){
  31.         new=mymalloc(ICS);
  32.         new->code=branch;
  33.         new->typf=label;
  34.         add_IC(new);
  35.     }
  36. }
  37.  
  38. void inline_memcpy(np z,np q,zlong size)
  39. /*  fuegt ein ASSIGN-IC ein, das memcpy(z,q,size) entspricht    */
  40. {
  41.     struct IC *new=mymalloc(ICS);
  42.     if((z->ntyp->flags&NQ)!=POINTER) ierror(0);
  43.     if((q->ntyp->flags&NQ)!=POINTER) ierror(0);
  44.  
  45.     gen_IC(z,0,0);
  46.     if(z->o.flags&DREFOBJ){
  47.         struct IC *n2=mymalloc(ICS);
  48.         n2->code=ASSIGN;
  49.         n2->typf=q->ntyp->flags;
  50.         n2->q1=z->o;
  51.         get_scratch(&n2->z,z->ntyp->flags,z->ntyp->next->flags,z->ntyp);
  52.         n2->q2.flags=0;
  53.         n2->q2.val.vlong=sizetab[POINTER];
  54.         new->z=n2->z;
  55.         add_IC(n2);
  56.     }else{
  57.         new->z=z->o;
  58.     }
  59.     if(new->z.flags&VARADR) new->z.flags&=~VARADR; else new->z.flags|=DREFOBJ;
  60.  
  61.     gen_IC(q,0,0);
  62.     if(q->o.flags&DREFOBJ){
  63.         struct IC *n2=mymalloc(ICS);
  64.         n2->code=ASSIGN;
  65.         n2->typf=q->ntyp->flags;
  66.         n2->q1=q->o;
  67.         get_scratch(&n2->z,q->ntyp->flags,q->ntyp->next->flags,q->ntyp);
  68.         n2->q2.flags=0;
  69.         n2->q2.val.vlong=sizetab[POINTER];
  70.         new->q1=n2->z;
  71.         add_IC(n2);
  72.     }else{
  73.         new->q1=q->o;
  74.     }
  75.     if(new->q1.flags&VARADR) new->q1.flags&=~VARADR; else new->q1.flags|=DREFOBJ;
  76.  
  77.     new->code=ASSIGN;
  78.     new->typf=UNSIGNED|CHAR;
  79.     new->q2.flags=0;
  80.     new->q2.val.vlong=size;
  81.     add_IC(new);
  82. }
  83.  
  84. void add_IC(struct IC *new)
  85. /*  fuegt ein IC ein                                            */
  86. {
  87.     int code;
  88.     if(!new) return;
  89.     if(nocode) {free(new);return;}
  90.     new->next=0;
  91.     new->q1.am=new->q2.am=new->z.am=0;
  92.     new->line=line; new->file=0;
  93.     code=new->code;
  94.     if(code>=BEQ&&code<=BRA) new->q1.flags=new->q2.flags=new->z.flags=0;
  95.     if(code==ALLOCREG||code==FREEREG||code==SAVEREGS||code==RESTOREREGS) new->typf=0;
  96.     if(DEBUG&64){ pric(stdout,first_ic);printf("new\n");pric2(stdout,new);printf("-\n");}
  97.     if(new->q1.flags&VAR){
  98.         if(!new->q1.v) ierror(0);
  99.         new->q1.v->flags|=USEDASSOURCE;
  100.         if(code==ADDRESS||(new->q1.flags&VARADR)) new->q1.v->flags|=USEDASADR;
  101.         new->q1.v->priority+=currentpri;
  102.     }
  103.     if(new->q2.flags&VAR){
  104.         if(!new->q2.v) ierror(0);
  105.         new->q2.v->flags|=USEDASSOURCE;
  106.         if(code==ADDRESS||(new->q2.flags&VARADR)) new->q2.v->flags|=USEDASADR;
  107.         new->q2.v->priority+=currentpri;
  108.     }
  109.     if(new->z.flags&VAR){
  110.         if(!new->z.v) ierror(0);
  111.         if(new->z.flags&DREFOBJ) new->z.v->flags|=USEDASSOURCE; else new->z.v->flags|=USEDASDEST;
  112.         new->z.v->priority+=currentpri;
  113.     }
  114.     if(/*(c_flags_val[0].l&2)&&*/code==LABEL){
  115.     /*  entfernt Spruenge zu direkt folgenden Labels    */
  116.         struct IC *p=last_ic;
  117.         while(p){
  118.             if(p->typf==new->typf&&p->code>=BEQ&&p->code<=BRA){
  119.                 struct IC *n;
  120.                 if(DEBUG&1) printf("%s l%d deleted\n",ename[p->code],p->typf);
  121.                 n=p->next;
  122.                 remove_IC(p);
  123.                 p=n;
  124.             }else{
  125.                 if(p->code!=LABEL) break;
  126.                 p=p->prev;
  127.             }
  128.         }
  129.     }
  130.     if(last_ic){
  131.         if(code==ASSIGN){
  132.             if((last_ic->z.flags&(REG|SCRATCH|DREFOBJ))==(REG|SCRATCH)&&(new->q1.flags==last_ic->z.flags)&&last_ic->z.reg==new->q1.reg/*&&last_ic->code!=CALL*/){
  133.                 if(USEQ2ASZ||!(last_ic->q2.flags®)||!(new->z.flags®)||last_ic->q2.reg!=new->z.reg){
  134.                     if(USEQ2ASZ||!(last_ic->q2.flags&VAR)||!(new->z.flags&VAR)||last_ic->q2.v!=new->z.v){
  135.                     /*  verbindet op a,b->reg,move reg->c zu op a,b->c  */
  136.                     /*  hier fehlt aber noch Registerfreigabe           */
  137.                         last_ic->z=new->z;
  138.                         if(DEBUG&1) printf("move and op combined\n");
  139.                         if((new->q1.flags&SCRATCH)&&(new->q1.reg!=new->z.reg||!(new->z.flags®)))
  140.                             free_reg(new->q1.reg);
  141.                         free(new);
  142.                         return;
  143.                     }
  144.                 }
  145.             }
  146.             if((last_ic->z.flags&(VAR|SCRATCH|DREFOBJ))==(VAR|SCRATCH)&&(new->q1.flags==last_ic->z.flags)&&last_ic->z.v==new->q1.v/*&&last_ic->code!=CALL*/){
  147.                 if(USEQ2ASZ||!(last_ic->q2.flags®)||!(new->z.flags®)||last_ic->q2.reg!=new->z.reg){
  148.                     if(USEQ2ASZ||!(last_ic->q2.flags&VAR)||!(new->z.flags&VAR)||last_ic->q2.v!=new->z.v){
  149.                     /*  verbindet op a,b->scratch,move scratch->c zu op a,b->c  */
  150.                     /*  hier fehlt aber noch Registerfreigabe           */
  151.                         last_ic->z=new->z;
  152.                         if(DEBUG&1) printf("move and op combined(2)\n");
  153. /*                        if((new->q1.flags&SCRATCH)&&(new->q1.reg!=new->z.reg||!(new->z.flags®)))
  154.                             free_reg(new->q1.reg);*/
  155.                         free(new);
  156.                         return;
  157.                     }
  158.                 }
  159.             }
  160.  
  161.         }
  162.         if(last_ic->code==BRA){
  163.             if(code!=LABEL&&code!=ALLOCREG&&code!=FREEREG){
  164.             /*  loescht alles nach bra bis ein Label kommt  */
  165.             /*  momentan noch nicht perfekt, da es bei alloc/freereg stoppt */
  166.                 free(new);
  167.                 if(DEBUG&1) printf("Unreachable Statement deleted\n");
  168.                 return;
  169.             }
  170.             if(last_ic->prev&&code==LABEL){
  171.             /*  ersetzt bcc l1;bra l2;l1 durch b!cc l2      */
  172.                 if(last_ic->prev->code>=BEQ&&last_ic->prev->code<=BGT&&new->typf==last_ic->prev->typf){
  173.                     if(DEBUG&1) printf("%s l%d;%s l%d; substituted\n",ename[last_ic->prev->code],last_ic->prev->typf,ename[last_ic->code],last_ic->typf);
  174.                     if(last_ic->prev->code&1) last_ic->prev->code--;
  175.                                     else      last_ic->prev->code++;
  176.                     last_ic->prev->typf=last_ic->typf;
  177.                     last_ic=last_ic->prev;
  178.                     free(last_ic->next);
  179.                     last_ic->next=new;new->prev=last_ic;
  180.                     last_ic=new;
  181.                     return;
  182.                 }
  183.             }
  184.         }
  185. /*        }*/
  186.         new->prev=last_ic;
  187.         last_ic->next=new;
  188.         last_ic=new;
  189.     }else{
  190.         last_ic=new;first_ic=new;new->prev=0;
  191.     }
  192.     ic_count++;
  193.     /*  Merken, on Fliesskomma benutzt wurde    */
  194.     if(code!=LABEL&&(code<BEQ||code>BRA)){
  195.         if((new->typf&NQ)==FLOAT||(new->typf&NQ)==DOUBLE) float_used=1;
  196.         if(code==CONVFLOAT||code==CONVDOUBLE) float_used=1;
  197.     }
  198.     if((new->q1.flags&SCRATCH)&&(new->q1.reg!=new->z.reg||!(new->z.flags®)))
  199.         free_reg(new->q1.reg);
  200.     if((new->q2.flags&SCRATCH)&&(new->q2.reg!=new->z.reg||!(new->z.flags®)))
  201.         free_reg(new->q2.reg);
  202. }
  203. void gen_IC(np p,int ltrue,int lfalse)
  204. /*  Erzeugt eine IC-Liste aus einer expression      */
  205. {
  206.     struct IC *new; struct regargs_list *rl;
  207.     if(!p) return;
  208.     if(p->flags==STRING){
  209.     /*  hier fehlt noch die Verwaltung der String-Inhalte   */
  210.         p->o.v=add_var(empty,clone_typ(p->ntyp),STATIC,p->cl);
  211.         p->o.v->flags|=DEFINED;
  212.         p->o.flags=VAR;
  213.         p->o.reg=0;
  214.         p->o.val=p->val;
  215.         return;
  216.     }
  217.     if(p->flags==IDENTIFIER){
  218. /*        p->o.v=find_var(p->identifier,0);*/
  219.         p->o.flags=VAR;
  220.         p->o.reg=0;
  221.         p->o.val=p->val;
  222.         return;
  223.     }
  224.     if(p->flags==CEXPR||p->flags==PCEXPR){
  225.         if(p->left){
  226.             if(p->left->flags==POSTINC) p->left->flags=PREINC;
  227.             if(p->left->flags==POSTDEC) p->left->flags=PREDEC;
  228.             gen_IC(p->left,0,0);
  229.             if(p->left->o.flags&SCRATCH) free_reg(p->left->o.reg);
  230.         }
  231.         if(p->right){
  232.             if(p->right->flags==POSTINC) p->right->flags=PREINC;
  233.             if(p->right->flags==POSTDEC) p->right->flags=PREDEC;
  234.             gen_IC(p->right,0,0);
  235.             if(p->right->o.flags&SCRATCH) free_reg(p->right->o.reg);
  236.         }
  237.         p->o.flags=KONST;
  238.         p->o.val=p->val;
  239.         p->o.reg=0;
  240.         return;
  241.     }
  242.     if(p->flags==KOMMA){
  243.         if(p->left->sidefx){
  244.             gen_IC(p->left,0,0);
  245.             if(p->left->o.flags&SCRATCH) free_reg(p->left->o.reg);
  246.         } else error(129);
  247.         gen_IC(p->right,0,0);
  248.         p->o=p->right->o;
  249.         return;
  250.     }
  251.     if(p->flags==CAST){
  252.         gen_IC(p->left,0,0);
  253.         if((p->ntyp->flags&NQ)==VOID){
  254.             if(p->left->o.flags&SCRATCH) free_reg(p->left->o.reg);
  255.             p->o.flags=0;
  256.         }else{
  257.             convert(p->left,p->ntyp->flags&NU);
  258.             p->o=p->left->o;
  259.         }
  260.         return;
  261.     }
  262.     if(p->flags==FIRSTELEMENT){
  263.         gen_IC(p->left,0,0);
  264.         p->o=p->left->o;
  265.         return;
  266.     }
  267.     new=mymalloc(ICS);
  268.     new->typf=p->ntyp->flags&NU;
  269.     new->q1.reg=new->q2.reg=new->z.reg=0;
  270.     new->q1.flags=new->q2.flags=new->z.flags=0;
  271.     if((p->flags>=LSHIFT&&p->flags<=MOD)||(p->flags>=OR&&p->flags<=AND)||p->flags==PMULT){
  272.         do_arith(p,new,0,0);
  273.         return;
  274.     }
  275.     if(p->flags==CONTENT){
  276.         gen_IC(p->left,0,0);
  277.         if(p->left->o.flags&VARADR){
  278.             free(new);
  279.             p->o=p->left->o;
  280.             p->o.flags&=~VARADR;
  281.             return;
  282.         }
  283.         if(!(p->left->o.flags&DREFOBJ)){
  284.             free(new);
  285.             p->o=p->left->o;
  286.             p->o.flags|=DREFOBJ;
  287.             return;
  288.         }
  289.         if(p->left->o.flags&SCRATCH){
  290.             new->z=p->left->o;
  291.             new->z.flags&=~DREFOBJ;
  292.         }else{
  293.             /*  hier muss man noch was aender, da das so nicht funktioniert */
  294.             get_scratch(&new->z,p->left->ntyp->flags,p->ntyp->flags,p->left->ntyp);
  295.         }
  296.         new->code=ASSIGN;new->typf=POINTER;
  297.         new->q1=p->left->o;
  298.         new->q2.val.vlong=sizetab[POINTER];
  299.         p->o=new->z;
  300.         add_IC(new);
  301.         p->o.flags|=DREFOBJ;
  302.         return;
  303.     }
  304.     if(p->flags==ASSIGN){
  305.         new->code=ASSIGN;
  306.         gen_IC(p->right,0,0);
  307.         gen_IC(p->left,0,0);
  308.         convert(p->right,p->ntyp->flags&NU);
  309.         new->q1=p->right->o;
  310.         new->z=p->left->o;
  311.         new->q2.val.vlong=szof(p->left->ntyp);
  312.         p->o=new->z;
  313.         add_IC(new);
  314.         return;
  315.     }
  316.     if(p->flags==ASSIGNADD){
  317.     /*  das hier ist nicht besonders schoen */
  318.         struct obj o;struct IC *n;int f;
  319.         if(p->right->right==0){
  320.         /*  sowas wie a+=0 wurde wegoptimiert   */
  321.             free(new);
  322.             p->o=p->left->o;
  323.             return;
  324.         }
  325.         f=do_arith(p->right,new,p->left,&o);
  326.         if(!f) {ierror(0);return;}
  327.         if(f>1) {ierror(0);return;}
  328.         if(!nocode&&(o.flags&(SCRATCH|REG))==(SCRATCH|REG)&&!regs[o.reg]){
  329.         /*  ueberfluessiges FREEREG entfernen   */
  330.             n=last_ic;
  331.             while(n){
  332.                 if(n->code==FREEREG&&n->q1.reg==o.reg){
  333.                     remove_IC(n);if(!nocode) regs[o.reg]=1;
  334.                     break;
  335.                 }
  336.                 n=n->prev;
  337.             }
  338.         }
  339.         convert(p->right,p->ntyp->flags&NU);
  340.         new=mymalloc(ICS);
  341.         new->typf=p->ntyp->flags&NU;
  342.         new->q2.flags=0;
  343.         new->code=ASSIGN;
  344.         new->q1=p->right->o;
  345.         new->z=o;
  346.         new->q2.val.vlong=szof(p->left->ntyp);
  347.         p->o=new->z;
  348.         add_IC(new);
  349.         return;
  350.     }
  351.     if(p->flags==MINUS||p->flags==KOMPLEMENT){
  352.         new->code=p->flags;
  353.         gen_IC(p->left,0,0);
  354.         convert(p->left,p->ntyp->flags);
  355.         if(regok(p->left->o.reg,p->ntyp->flags,0)&&(p->left->o.flags&SCRATCH)){
  356.             new->z=p->left->o;
  357.             new->z.flags&=~DREFOBJ;
  358.         }else{
  359.             get_scratch(&new->z,p->left->ntyp->flags,0,p->left->ntyp);
  360.         }
  361.         new->q1=p->left->o;
  362.         p->o=new->z;
  363.         add_IC(new);
  364.         return;
  365.     }
  366.     if(p->flags==ADDRESS||p->flags==ADDRESSA||p->flags==ADDRESSS){
  367.         new->code=ADDRESS;
  368.         new->typf=p->left->ntyp->flags&NU;
  369.         gen_IC(p->left,0,0);
  370.         if(p->left->o.flags&VAR) p->left->o.v->flags|=USEDASSOURCE|USEDASDEST;
  371.         if(p->left->o.flags&DREFOBJ){
  372.             free(new);
  373.             p->o=p->left->o;
  374.             p->o.flags&=~DREFOBJ;
  375.             return;
  376.         }
  377.         if((p->left->o.flags&VAR)&&!(p->left->o.flags&VARADR)
  378.            &&(p->left->o.v->storage_class==EXTERN||p->left->o.v->storage_class==STATIC)){
  379.             free(new);
  380.             p->o=p->left->o;
  381.             p->o.flags|=VARADR;
  382.             return;
  383.         }
  384.         new->q1=p->left->o;
  385.         get_scratch(&new->z,POINTER,p->ntyp->next->flags,0);
  386.         p->o=new->z;
  387.         add_IC(new);
  388.         return;
  389.     }
  390.     if(p->flags==LAND||p->flags==LOR){
  391.         int l1,l2,l3,l4;
  392. /*        printf("%s true=%d false=%d\n",ename[p->flags],ltrue,lfalse);*/
  393.         l1=++label;if(!ltrue) {l2=++label;l3=++label;l4=++label;}
  394.         if(!ltrue){if(p->flags==LAND) gen_IC(p->left,l1,l3);
  395.                     else gen_IC(p->left,l3,l1);
  396.         }else     {if(p->flags==LAND) gen_IC(p->left,l1,lfalse);
  397.                     else gen_IC(p->left,ltrue,l1);
  398.         }
  399.         if(p->left->o.flags!=0){
  400.             if(p->flags==LAND)
  401.                 gen_test(&p->left->o,p->left->ntyp->flags,BEQ,((!ltrue)?l3:lfalse));
  402.             else
  403.                 gen_test(&p->left->o,p->left->ntyp->flags,BNE,((!ltrue)?l3:ltrue));
  404.         }
  405.         gen_label(l1);
  406.         if(!ltrue){if(p->flags==LAND) gen_IC(p->right,l2,l3);
  407.                     else gen_IC(p->right,l3,l2);
  408.         }else      gen_IC(p->right,ltrue,lfalse);
  409.         if(p->right->o.flags!=0){
  410.             if(p->flags==LAND)
  411.                 gen_test(&p->right->o,p->right->ntyp->flags,BEQ,((!ltrue)?l3:lfalse));
  412.             else
  413.                 gen_test(&p->right->o,p->right->ntyp->flags,BNE,((!ltrue)?l3:ltrue));
  414.         }
  415.         if(!ltrue){
  416.             gen_label(l2);
  417.             if(p->flags==LAND) gen_cond(&p->o,0,l3,l4); else gen_cond(&p->o,1,l3,l4);
  418.         }else{
  419.             new=mymalloc(ICS);
  420.             new->code=BRA;
  421.             if(p->flags==LAND) new->typf=ltrue; else new->typf=lfalse;
  422.             add_IC(new);
  423.         }
  424.         if(ltrue) p->o.flags=0;
  425.         return;
  426.     }
  427.     if(p->flags==NEGATION){
  428.         int l1,l2,l3;
  429.         if(!ltrue) {l1=++label;l2=++label;l3=++label;}
  430.         if(ltrue) gen_IC(p->left,lfalse,ltrue); else gen_IC(p->left,l1,l3);
  431.         if(!p->left->o.flags) {free(new);p->o.flags=0;
  432.         }else{
  433.             gen_test(&p->left->o,p->left->ntyp->flags,BNE,((!ltrue)?l1:lfalse));
  434.         }
  435.         if(ltrue){
  436.             new=mymalloc(ICS);
  437.             new->code=BRA;
  438.             if(!ltrue) new->typf=l2; else new->typf=ltrue;
  439.             add_IC(new);
  440.             p->o.flags=0;
  441.         }else{
  442.             gen_label(l3);
  443.             gen_cond(&p->o,0,l1,l2);
  444.         }
  445.         return;
  446.     }
  447.     if(p->flags>=EQUAL&&p->flags<=GREATEREQ){
  448.         int l1,l2,l3,tl,tr,swapped;
  449.         if(!ltrue) {l1=++label;l2=++label;l3=++label;}
  450.         if(p->left->flags==CEXPR){
  451.         /*  Konstanten nach rechts  */
  452.             np merk;merk=p->left;p->left=p->right;p->right=merk;
  453.             swapped=1;
  454.         }else swapped=0;
  455.         new->code=COMPARE;
  456.         tl=p->left->ntyp->flags&NU;tr=p->right->ntyp->flags&NU;
  457.         if(p->right->flags==CEXPR&&(tr&NQ)<FLOAT&&(tl&NQ)<FLOAT){
  458.             int negativ;
  459.             eval_constn(p->right);
  460.             if(zlleq(vlong,0)) negativ=1; else negativ=0;
  461.             if((tl&UNSIGNED)||(tr&UNSIGNED)) negativ=0;
  462.             if((!negativ||zlleq(t_min[tl],vlong))&&(negativ||zulleq(vulong,t_max[tl]))){
  463.                 convert(p->right,tl);
  464.                 tr=tl;
  465.             }
  466.         }
  467.         if(arith(tl&NQ)&&(tl!=tr||!shortcut(COMPARE,tl))){
  468.             struct Typ *t;
  469.             t=arith_typ(p->left->ntyp,p->right->ntyp);
  470.             new->typf=t->flags&NU;
  471.             freetyp(t);
  472.         }else{
  473.             new->typf=p->left->ntyp->flags&NU;
  474.         }
  475.         gen_IC(p->left,0,0);
  476.         convert(p->left,new->typf);
  477.         gen_IC(p->right,0,0);
  478.         convert(p->right,new->typf);
  479.         new->q1=p->left->o;
  480.         new->q2=p->right->o;
  481.         new->z.flags=0;
  482.         add_IC(new);
  483.         new=mymalloc(ICS);
  484.         if(p->flags==EQUAL) new->code=BEQ;
  485.         if(p->flags==INEQUAL) new->code=BNE;
  486.         if(p->flags==LESS) {if(swapped) new->code =BGT; else new->code=BLT;}
  487.         if(p->flags==LESSEQ){if(swapped) new->code=BGE; else new->code=BLE;}
  488.         if(p->flags==GREATER){if(swapped) new->code=BLT; else new->code=BGT;}
  489.         if(p->flags==GREATEREQ){if(swapped) new->code=BLE; else new->code=BGE;}
  490.         if(ltrue) new->typf=ltrue; else new->typf=l1;
  491.         add_IC(new);
  492.         if(ltrue){
  493.             new=mymalloc(ICS);
  494.             new->code=BRA;
  495.             new->typf=lfalse;
  496.             add_IC(new);
  497.             p->o.flags=0;
  498.         }else{
  499.             gen_label(l3);
  500.             gen_cond(&p->o,1,l1,l2);
  501.         }
  502.         return;
  503.     }
  504.     if(p->flags==CALL){
  505.         int r=0;struct obj *op,ret_obj;zlong sz;
  506.         int mregs[MAXR+1];
  507.         if(p->left->flags==ADDRESS&&p->left->left->flags==IDENTIFIER){
  508.             struct Var *v;
  509.             gen_IC(p->left,0,0); r=1;
  510.             v=p->left->o.v;
  511.             if(v->fi&&v->fi->first_ic&&(c_flags_val[0].l&4096)){
  512.             /*  function call inlining  */
  513.                 struct argument_list *al;
  514.                 struct Var *vp,**argl1,**argl2;
  515.                 struct IC *ip;int lc;
  516.                 int arg_cnt=0,i;
  517.                 if(DEBUG&1024){
  518.                     printf("inlining call to <%s>\n",v->identifier);
  519.                     for(vp=v->fi->vars;vp;vp=vp->next)
  520.                         printf("%s(%ld)\n",vp->identifier,zl2l(vp->offset));
  521.                 }
  522.                 for(vp=v->fi->vars;vp;vp=vp->next){
  523.                     if((zleqto(vp->offset,l2zl(0L))||vp->reg)&&*vp->identifier&&(vp->storage_class==AUTO||vp->storage_class==REGISTER)) arg_cnt++;
  524.                 }
  525.  
  526.                 /*  Argumente in die ersten Parametervariablen kopieren */
  527.                 argl1=mymalloc(arg_cnt*sizeof(struct Var *));
  528.                 argl2=mymalloc(arg_cnt*sizeof(struct Var *));
  529.  
  530.                 al=p->alist;vp=v->fi->vars;i=0;
  531.                 while(al){
  532.                     while(vp&&(!*vp->identifier||(!zleqto(vp->offset,l2zl(0L))&&!vp->reg)||(vp->storage_class!=REGISTER&&vp->storage_class!=AUTO))) vp=vp->next;
  533.                     if(!vp){ error(39); break; }
  534.                     if(i>=arg_cnt) ierror(0);
  535.                     if(DEBUG&1024) printf("arg: %s(%ld)\n",vp->identifier,zl2l(vp->offset));
  536.                     argl1[i]=vp;
  537.                     argl2[i]=add_var(empty,clone_typ(vp->vtyp),vp->storage_class,0);
  538.                     if(!al->arg) ierror(0);
  539.                     gen_IC(al->arg,0,0);
  540.                     convert(al->arg,vp->vtyp->flags);
  541.                     new=mymalloc(ICS);
  542.                     new->code=ASSIGN;
  543.                     new->q1=al->arg->o;
  544.                     new->q2.flags=0;
  545.                     new->q2.val.vlong=szof(vp->vtyp);
  546.                     new->z.flags=VAR;
  547.                     new->z.val.vlong=l2zl(0L);
  548.                     new->z.v=argl2[i];
  549.                     new->typf=vp->vtyp->flags;
  550.                     add_IC(new);
  551.                     i++;
  552.                     al=al->next;
  553.                     vp=vp->next;
  554.                 }
  555.                 if(i<arg_cnt){ error(83); arg_cnt=i;}
  556.  
  557.                 /*  Kopien der Variablen erzeugen   */
  558.                 for(vp=v->fi->vars;vp;vp=vp->next){
  559.                     vp->inline_copy=0;
  560.                 }
  561.                 for(i=0;i<arg_cnt;i++){
  562.                     if(argl1[i]){
  563.                         if(!argl2[i]) ierror(0);
  564.                         argl1[i]->inline_copy=argl2[i];
  565.                     }
  566.                 }
  567.  
  568.                 /*  Rueckgabewert   */
  569.                 if((p->ntyp->flags&NQ)!=VOID){
  570.                     p->o.flags=SCRATCH|VAR;
  571.                     p->o.reg=0;p->o.val.vlong=l2zl(0L);
  572.                     p->o.v=add_var(empty,clone_typ(p->ntyp),AUTO,0);
  573.                 }else{
  574.                     p->o.flags=0;
  575.                 }
  576.  
  577.                 free(argl1);
  578.                 free(argl2);
  579.  
  580.                 /*  Code einfuegen und Labels umschreiben   */
  581.                 ip=v->fi->first_ic;lc=0;
  582.                 while(ip){
  583.                     struct Var *iv;
  584.                     int c;
  585.                     new=mymalloc(ICS);
  586.                     memcpy(new,ip,ICS);
  587.                     c=ip->code;
  588.                     /*  evtl. ist ein IC praktisch ein SETRETURN, falls das */
  589.                     /*  Rueckgabeziel ueber Parameterzeiger angespr. wird   */
  590.                     if(ip->z.flags&VAR){
  591.                       iv=ip->z.v;
  592.                       if(iv->storage_class==AUTO||iv->storage_class==REGISTER){
  593.                         if(!*iv->identifier&&zleqto(iv->offset,l2zl(0L))){
  594.                           new->z=p->o;
  595.                         }else{
  596.                           if(!iv->inline_copy){
  597.                             iv->inline_copy=add_var(empty,clone_typ(iv->vtyp),iv->storage_class,0);
  598.                             iv->inline_copy->reg=iv->reg;
  599.                           }
  600.                           new->z.v=iv->inline_copy;
  601.                         }/*else if(iv->inline_copy) ierror(0);*/
  602.                       }
  603.                     }
  604.                     /*  Kopien aller auto/register Variablen erzeugen   */
  605.                     if(ip->q1.flags&VAR){
  606.                       iv=ip->q1.v;
  607.                       if(iv->storage_class==AUTO||iv->storage_class==REGISTER){
  608.                         if(!iv->inline_copy){
  609.                           iv->inline_copy=add_var(empty,clone_typ(iv->vtyp),iv->storage_class,0);
  610.                           iv->inline_copy->reg=iv->reg;
  611.                         }
  612.                         new->q1.v=iv->inline_copy;
  613.                       }/*else if(iv->inline_copy) ierror(0);*/
  614.                     }
  615.                     if(ip->q2.flags&VAR){
  616.                       iv=ip->q2.v;
  617.                       if(iv->storage_class==AUTO||iv->storage_class==REGISTER){
  618.                         if(!iv->inline_copy){
  619.                           iv->inline_copy=add_var(empty,clone_typ(iv->vtyp),iv->storage_class,0);
  620.                           iv->inline_copy->reg=iv->reg;
  621.                         }
  622.                         new->q2.v=iv->inline_copy;
  623.                       }/*else if(iv->inline_copy) ierror(0);*/
  624.                     }
  625.                     if(c==CALL) function_calls+=currentpri;
  626.                     if(c==LABEL||(c>=BEQ&&c<=BRA)){
  627.                         if(new->typf>lc) lc=new->typf;
  628.                         new->typf+=label;
  629.                     }
  630.                     if(c==SETRETURN){
  631.                         new->code=ASSIGN;
  632.                         new->z=p->o;
  633.                     }
  634.                     add_IC(new);
  635.                     ip=ip->next;
  636.                 }
  637.                 label+=lc;
  638.                 return;
  639.             }
  640.             /*  einige spezielle Inline-Funktionen; das setzt voraus, dass  */
  641.             /*  diese in den Headerfiles passend deklariert werden          */
  642.             if(v->storage_class==EXTERN){
  643.                 if(!strcmp(v->identifier,"strlen")&&p->alist&&p->alist->arg){
  644.                     np n=p->alist->arg;
  645.                     if(n->flags==ADDRESSA&&n->left->flags==STRING){
  646.                         struct const_list *cl;zulong len=ul2zul(0UL);
  647.                         cl=n->left->cl;
  648.                         while(cl){
  649.                             if(zleqto(l2zl(0L),zc2zl(cl->other->val.vchar))) break;
  650.                             len=zuladd(len,ul2zul(1UL));
  651.                             cl=cl->next;
  652.                         }
  653.                         p->o.val.vulong=len;
  654.                         eval_const(&p->o.val,UNSIGNED|LONG);
  655.                         insert_const(p);
  656.                         insert_const2(&p->o.val,p->ntyp->flags);
  657.                         p->flags=CEXPR;
  658.                         p->o.flags=KONST;
  659.                         return;
  660.                     }
  661.                 }
  662.  
  663.                 if(INLINEMEMCPY>0&&(optflags&2)){
  664.                     if(!strcmp(v->identifier,"strcpy")&&p->alist&&p->alist->next&&p->alist->next->arg){
  665.                         np n=p->alist->next->arg;
  666.                         if(n->flags==ADDRESSA&&n->left->flags==STRING){
  667.                             struct const_list *cl;zlong len=l2zl(0L);
  668.                             cl=n->left->cl;
  669.                             while(cl){
  670.                                 len=zladd(len,l2zl(1L));
  671.                                 if(zleqto(zc2zl(cl->other->val.vchar),l2zl(0L))) break;
  672.                                 cl=cl->next;
  673.                             }
  674.                             if(zlleq(len,l2zl((long)INLINEMEMCPY))){
  675.                                 inline_memcpy(p->alist->arg,n,len);
  676.                                 p->o=p->alist->arg->o;
  677.                                 return;
  678.                             }
  679.                         }
  680.                     }
  681.                     if(!strcmp(v->identifier,"memcpy")){
  682.                         if(p->alist&&p->alist->next&&p->alist->next->next
  683.                            &&p->alist->next->next->arg
  684.                            &&p->alist->next->next->arg->flags==CEXPR){
  685.                             eval_constn(p->alist->next->next->arg);
  686.                             if(zlleq(vlong,l2zl((long)INLINEMEMCPY))){
  687.                                 inline_memcpy(p->alist->arg,p->alist->next->arg,vlong);
  688.                                 p->o=p->alist->arg->o;
  689.                                 return;
  690.                             }
  691.                         }
  692.                     }
  693.                 }
  694.             }
  695.         }
  696.         rl=0;
  697.         if(!(optflags&2)){
  698.           int r;
  699.           for(r=1;r<=MAXR;r++){mregs[r]=regs[r];regs[r]&=~32;}
  700.         }
  701. #ifdef HAVE_REGPARMS
  702.         if(!freturn(p->ntyp)){
  703.           struct IC *new2;
  704.           new2=mymalloc(ICS);
  705.           new2->code=ADDRESS;
  706.           new2->typf=p->ntyp->flags&NU;
  707.           new2->q1.flags=VAR;
  708.           new2->q1.v=add_var(empty,clone_typ(p->ntyp),AUTO,0);
  709.           new2->q1.val.vlong=l2zl(0L);
  710.           op=&new2->q1;
  711.           new2->q2.flags=0;
  712.           get_scratch(&new2->z,POINTER,p->ntyp->flags&NU,0);
  713.           ret_obj=new2->z;
  714.           add_IC(new2);
  715.         }
  716.         {
  717.             struct reg_handle reg_handle=empty_reg_handle;
  718.             if(!freturn(p->ntyp)){
  719.               static struct Typ ptyp={POINTER};
  720.               int reg;
  721.               ptyp.next=p->ntyp;
  722.               reg=reg_parm(®_handle,&ptyp);
  723.               if(!reg) ierror(0);
  724.               sz=push_args(p->alist,p->left->ntyp->next->exact,0,&rl,®_handle,&ret_obj,reg);
  725.             }else{
  726.               sz=push_args(p->alist,p->left->ntyp->next->exact,0,&rl,®_handle,0,-1);
  727.             }
  728.         }
  729. #else
  730.         sz=push_args(p->alist,p->left->ntyp->next->exact,0,&rl);
  731. #endif
  732.         if(!r) gen_IC(p->left,0,0);
  733.         if(!(p->left->o.flags&DREFOBJ)){
  734.             free(new);
  735.             p->o=p->left->o;
  736.             if(p->o.flags&VARADR) p->o.flags&=~VARADR;
  737.              else p->o.flags|=DREFOBJ;
  738.         }else{
  739.             if(p->left->o.flags&VARADR){
  740.                 free(new);
  741.                 p->o=p->left->o;
  742.                 p->o.flags&=~VARADR;
  743.             }else{
  744.                 if(p->left->o.flags&SCRATCH){
  745.                     new->z=p->left->o;
  746.                     new->z.flags&=~DREFOBJ;
  747.                 }else{
  748.                 /* das hier funktioniert vermutlich auch nicht  */
  749.                     get_scratch(&new->z,p->left->ntyp->flags,p->ntyp->flags,p->left->ntyp);
  750.                 }
  751.                 new->code=ASSIGN;new->typf=POINTER;
  752.                 new->q1=p->left->o;
  753.                 new->q2.val.vlong=sizetab[POINTER];
  754.                 new->q2.flags=0;
  755.                 p->o=new->z;
  756.                 add_IC(new);
  757.                 p->o.flags|=DREFOBJ;
  758.             }
  759.         }
  760. /*            p->left->o.flags-=DREFOBJ|VARADR; Was sollte das??    */
  761.  
  762.         if(optflags&2){
  763.             while(rl){
  764.                 struct regargs_list *m;
  765.                 new=mymalloc(ICS);
  766.                 new->code=NOP;
  767.                 new->q1.flags=VAR;
  768.                 new->q1.v=rl->v;
  769.                 new->q1.val.vlong=l2zl(0L);
  770.                 new->typf=0;
  771.                 new->q2.flags=new->z.flags=0;
  772.                 add_IC(new);
  773.                 m=rl->next;free(rl);rl=m;
  774.             }
  775.         }
  776. #ifndef HAVE_REGPARMS
  777.         /*  gegebenenfalls Adresse des Ziels auf den Stack  */
  778.         if(!freturn(p->ntyp)){
  779. #ifdef ORDERED_PUSH
  780.             ierror(0);
  781. #endif
  782.             new=mymalloc(ICS);
  783.             new->code=ADDRESS;
  784.             new->typf=p->ntyp->flags&NU;
  785.             new->q1.flags=VAR;
  786.             new->q1.v=add_var(empty,clone_typ(p->ntyp),AUTO,0);
  787.             new->q1.val.vlong=l2zl(0L);
  788.             op=&new->q1;
  789.             new->q2.flags=0;
  790.             get_scratch(&new->z,POINTER,p->ntyp->flags&NU,0);
  791.             ret_obj=new->z;
  792.             add_IC(new);
  793.             new=mymalloc(ICS);
  794.             new->code=PUSH;
  795.             new->typf=POINTER;
  796.             new->q1=ret_obj;
  797.             new->q2.flags=new->z.flags=0;
  798.             new->q2.val.vlong=sizetab[POINTER];
  799.             add_IC(new);
  800.             sz=zladd(sz,sizetab[POINTER]);
  801.         }
  802. #endif
  803.         /*  Scratchregister evtl. sichern   */
  804.         savescratch(MOVEFROMREG,last_ic,0);
  805.         function_calls+=currentpri;
  806.         new=mymalloc(ICS);
  807.         new->code=CALL;
  808.         new->typf=FUNKT;
  809.         new->q1=p->o;
  810.         new->q2.flags=new->z.flags=0;
  811.         new->q2.val.vlong=sz; /*  Groesse der Parameter auf dem Stack */
  812.         add_IC(new);
  813.         r=0;
  814.         if((p->ntyp->flags&NQ)!=VOID){
  815.             new=mymalloc(ICS);
  816.             new->code=GETRETURN;
  817.             new->q1.flags=new->q2.flags=0;
  818.             new->q1.reg=freturn(p->ntyp);
  819.             new->q2.val.vlong=szof(p->ntyp);
  820.             new->typf=p->ntyp->flags;
  821.             if(freturn(p->ntyp)){
  822.                 int t=p->ntyp->flags&NQ;
  823.                 if(t==STRUCT||t==UNION){
  824.                     new->z.v=add_var(empty,clone_typ(p->ntyp),AUTO,0);
  825.                     new->z.flags=VAR;
  826.                     new->z.val.vlong=l2zl(0L);
  827.                 }else get_scratch(&new->z,p->ntyp->flags&NU,0,p->ntyp);
  828.             } else new->z=*op;
  829.             if((new->z.flags&(REG|DREFOBJ))==REG) r=new->z.reg;
  830.             p->o=new->z;
  831.             add_IC(new);
  832.         }else{
  833.             p->o.flags=0;
  834.         }
  835.         /*  Scratchregister evtl. wiederherstellen  */
  836.         savescratch(MOVETOREG,last_ic,r);
  837.         if(!(optflags&2)){
  838.           int r;
  839.           for(r=1;r<=MAXR;r++){
  840.             if(regs[r])
  841.               regs[r]|=(mregs[r]&32);
  842.           }
  843.         }
  844.         /*  Evtl. gespeicherte Registerargumente wiederherstellen.  */
  845.         while(rl){
  846.             struct regargs_list *m;
  847.             if(rl->v){
  848.                 new=mymalloc(ICS);
  849.                 new->code=MOVETOREG;
  850.                 new->typf=0;
  851.                 new->q1.flags=VAR|DONTREGISTERIZE;
  852.                 new->q1.v=rl->v;
  853.                 new->q1.val.vlong=l2zl(0L);
  854.                 new->z.flags=REG;
  855.                 new->z.reg=rl->reg;
  856.                 new->q2.flags=0;
  857.                 new->q2.val.vlong=regsize[rl->reg];
  858.                 add_IC(new);
  859.             }else{
  860.                 new=mymalloc(ICS);
  861.                 new->code=FREEREG;
  862.                 new->typf=0;
  863.                 new->q1.flags=REG;
  864.                 new->q2.flags=new->z.flags=0;
  865.                 new->q1.reg=rl->reg;
  866.                 add_IC(new);
  867.                 regs[rl->reg]=0;
  868.             }
  869.             m=rl->next;free(rl);rl=m;
  870.         }
  871.         return;
  872.     }
  873.     if(p->flags>=PREINC&&p->flags<=POSTDEC){
  874.         struct obj o;
  875.         gen_IC(p->left,0,0);
  876.         if(p->flags==POSTINC||p->flags==POSTDEC){
  877.             new=mymalloc(ICS);
  878.             new->code=ASSIGN;
  879.             new->typf=p->ntyp->flags&NU;
  880.             new->q2.val.vlong=sizetab[p->ntyp->flags&NQ];
  881.             new->q1=p->left->o;
  882.             new->q1.flags&=~SCRATCH;
  883.             get_scratch(&new->z,p->left->ntyp->flags&NU,0,p->left->ntyp);
  884.             new->q2.flags=0;
  885.             o=new->z;
  886.             add_IC(new);
  887.             new=mymalloc(ICS);
  888.         }else o=p->left->o;
  889.         if((p->left->ntyp->flags&NQ)==POINTER){
  890.             if(p->flags==PREINC||p->flags==POSTINC) new->code=ADDI2P; else new->code=SUBIFP;
  891.             vlong=szof(p->left->ntyp->next);
  892.             new->q2.val.vint=zl2zi(vlong);
  893.             new->typf=INT;
  894.             new->q1=p->left->o;
  895.             new->z=p->left->o;
  896.             new->q2.flags=KONST;
  897.             add_IC(new);
  898.         }else{
  899.             if(p->flags==PREINC||p->flags==POSTINC) new->code=ADD; else new->code=SUB;
  900.             new->typf=p->ntyp->flags&NU;
  901.             new->q1=p->left->o;
  902.             new->z=p->left->o;
  903.             new->q2.flags=KONST;
  904.             vlong=l2zl(1L);vulong=zl2zul(vlong);vdouble=zl2zd(vlong);
  905.             if(new->typf==CHAR) new->q2.val.vchar=zl2zc(vlong);
  906.             if(new->typf==SHORT) new->q2.val.vshort=zl2zs(vlong);
  907.             if(new->typf==INT) new->q2.val.vint=zl2zi(vlong);
  908.             if(new->typf==LONG) new->q2.val.vlong=vlong;
  909.             if(new->typf==(UNSIGNED|CHAR)) new->q2.val.vuchar=zul2zuc(vulong);
  910.             if(new->typf==(UNSIGNED|SHORT)) new->q2.val.vushort=zul2zus(vulong);
  911.             if(new->typf==(UNSIGNED|INT)) new->q2.val.vuint=zul2zui(vulong);
  912.             if(new->typf==(UNSIGNED|LONG)) new->q2.val.vulong=vulong;
  913.             if(new->typf==DOUBLE) new->q2.val.vdouble=vdouble;
  914.             if(new->typf==FLOAT) new->q2.val.vfloat=zd2zf(vdouble);
  915.             add_IC(new);
  916.         }
  917.         if(p->flags==POSTINC||p->flags==POSTDEC){
  918.             if(p->left->o.flags&SCRATCH) free_reg(p->left->o.reg);
  919.         }
  920.         p->o=o;
  921.         return;
  922.     }
  923.     if(p->flags==COND){
  924.         int ltrue,lfalse,lout;
  925.         ltrue=++label;lfalse=++label;lout=++label;
  926.         gen_IC(p->left,ltrue,lfalse);
  927.         if(!p->left->o.flags){
  928.             free(new);
  929.         }else{
  930.             if(p->left->flags!=CEXPR){
  931.                 gen_test(&p->left->o,p->left->ntyp->flags,BEQ,lfalse);
  932.             }else{
  933.                 eval_constn(p->left);
  934.                 if(zleqto(vlong,l2zl(0L))&&zuleqto(vulong,ul2zul(0UL))&&zdeqto(vdouble,d2zd(0.0))){
  935.                     gen_IC(p->right->right,0,0);
  936.                     p->o=p->right->right->o;
  937.                 }else{
  938.                     gen_IC(p->right->left,0,0);
  939.                     p->o=p->right->left->o;
  940.                 }
  941.                 return;
  942.             }
  943.         }
  944.         gen_label(ltrue);
  945.         gen_IC(p->right->left,0,0);
  946.         if((p->ntyp->flags&NQ)!=VOID){
  947.             convert(p->right->left,p->ntyp->flags&NU);
  948.             if((p->right->left->o.flags&(SCRATCH|DREFOBJ))==SCRATCH){
  949.                 p->o=p->right->left->o;
  950.             }else{
  951.                 get_scratch(&p->o,p->ntyp->flags&NU,0,p->ntyp);
  952.                 new=mymalloc(ICS);
  953.                 new->code=ASSIGN;
  954.                 new->q1=p->right->left->o;
  955.                 new->z=p->o;
  956.                 new->q2.flags=0;
  957.                 new->q2.val.vlong=szof(p->ntyp);
  958.                 new->typf=p->ntyp->flags&NU;
  959.                 p->o=new->z;
  960.                 add_IC(new);
  961.             }
  962.         }else p->o.flags=0;
  963.         new=mymalloc(ICS);
  964.         new->code=BRA;
  965.         new->typf=lout;
  966.         add_IC(new);
  967.         gen_label(lfalse);
  968.         gen_IC(p->right->right,0,0);
  969.         if((p->ntyp->flags&NQ)!=VOID){
  970.             convert(p->right->right,p->ntyp->flags&NU);
  971.             new=mymalloc(ICS);
  972.             new->code=ASSIGN;
  973.             new->q1=p->right->right->o;
  974.             new->z=p->o;
  975.             new->q2.flags=0;
  976.             new->q2.val.vlong=szof(p->ntyp);
  977.             new->typf=p->ntyp->flags&NU;
  978.             add_IC(new);
  979.         }
  980.         gen_label(lout);
  981.         return;
  982.     }
  983.     printf("Operation: %d=%s\n",p->flags,ename[p->flags]);
  984.     ierror(0);
  985.     free(new);
  986.     p->o.flags=0;
  987. }
  988. #ifdef HAVE_REGPARMS
  989. zlong push_args(struct argument_list *al,struct struct_declaration *sd,int n,struct regargs_list **rl,struct reg_handle *reg_handle,struct obj *radr,int rreg)
  990. #else
  991. zlong push_args(struct argument_list *al,struct struct_declaration *sd,int n,struct regargs_list **rl)
  992. #endif
  993. /*  Legt die Argumente eines Funktionsaufrufs in umgekehrter Reihenfolge    */
  994. /*  auf den Stack. Es wird Integer-Erweiterung vorgenommen und float wird   */
  995. /*  nach double konvertiert, falls kein Prototype da ist.                   */
  996. {
  997.     int t,reg;struct IC *new;struct regargs_list *nrl;zlong sz,of;struct obj *arg;
  998. #ifdef HAVE_REGPARMS
  999.     int stdreg;
  1000.     if(!al&&!radr) return(0);
  1001.     if(radr){
  1002.       stdreg=rreg;
  1003.     }else{
  1004.       if(n<sd->count) stdreg=reg_parm(reg_handle,(*sd->sl)[n].styp);
  1005.       else        stdreg=reg_parm(reg_handle,al->arg->ntyp);
  1006.     }
  1007.     reg=stdreg;
  1008. #else
  1009.     if(!al) return(0);
  1010.     reg=0;
  1011. #endif
  1012. #ifdef HAVE_REGPARMS
  1013.     if(!radr){
  1014. #endif
  1015.       if(!al->arg) ierror(0);
  1016.       if(!sd) ierror(0);
  1017.       if(n<sd->count){
  1018.         t=(*sd->sl)[n].styp->flags;sz=szof((*sd->sl)[n].styp);
  1019.         reg=(*sd->sl)[n].reg;
  1020.       }else{
  1021.         t=al->arg->ntyp->flags;sz=szof(al->arg->ntyp);
  1022.       }
  1023.       if((t&NQ)>=CHAR&&(t&NQ)<=LONG) {t=int_erw(t);sz=sizetab[t&NQ];}
  1024.       if((t&NQ)==FLOAT&&n>=sd->count) {t=DOUBLE;sz=sizetab[t];}
  1025. #ifdef HAVE_REGPARMS
  1026.     }else{
  1027.       t=POINTER;
  1028.     }
  1029. #endif
  1030.     sz=zlmult(zldiv(zladd(sz,zlsub(maxalign,l2zl(1L))),maxalign),maxalign);
  1031. #ifdef ORDERED_PUSH
  1032.     if(reg==0){
  1033.       gen_IC(al->arg,0,0);
  1034.       convert(al->arg,t&NU);
  1035.       /*  Parameteruebergabe ueber Stack. */
  1036.       new=mymalloc(ICS);
  1037.       new->code=PUSH;
  1038.       new->typf=t;
  1039.       new->q1=al->arg->o;
  1040.       new->q2.flags=new->z.flags=0;
  1041.       new->q2.val.vlong=sz;
  1042.       add_IC(new);
  1043.       if(!al->next) return sz;
  1044.     }
  1045. #endif
  1046. #ifdef HAVE_REGPARMS
  1047.     if(radr){
  1048.       if(al) of=push_args(al,sd,0,rl,reg_handle,0,0); else of=l2zl(0L);
  1049.     }else{
  1050.       if(al->next) of=push_args(al->next,sd,n+1,rl,reg_handle,0,0); else of=l2zl(0L);
  1051.     }
  1052. #else
  1053.     if(al->next) of=push_args(al->next,sd,n+1,rl); else of=l2zl(0L);
  1054. #endif
  1055. #ifdef ORDERED_PUSH
  1056.     if(reg==0) return zladd(of,sz);
  1057. #endif
  1058. #ifdef HAVE_REGPARMS
  1059.     if(radr){
  1060.       arg=radr;
  1061.     }else{
  1062.       gen_IC(al->arg,0,0);
  1063.       convert(al->arg,t&NU);
  1064.       arg=&al->arg->o;
  1065.     }
  1066. #else
  1067.     gen_IC(al->arg,0,0);
  1068.     convert(al->arg,t&NU);
  1069.     arg=&al->arg->o;
  1070. #endif
  1071.     if(reg==0){
  1072.         /*  Parameteruebergabe ueber Stack. */
  1073.         new=mymalloc(ICS);
  1074.         new->code=PUSH;
  1075.         new->typf=t;
  1076.         new->q1=*arg;
  1077.         new->q2.flags=new->z.flags=0;
  1078.         new->q2.val.vlong=sz;
  1079.         add_IC(new);
  1080.         return(zladd(of,sz));
  1081.     }else{
  1082.         /*  Parameteruebergabe in Register. */
  1083.         struct Var *v=0; struct Typ *t2;
  1084.         if(optflags&2){
  1085.         /*  Version fuer Optimizer. */
  1086.             t2=mymalloc(TYPS);
  1087.             t2->flags=t;
  1088.             if((t&NQ)==POINTER){
  1089.                 t2->next=mymalloc(TYPS);
  1090.                 t2->next->flags=VOID;
  1091.                 t2->next->next=0;
  1092.             }else t2->next=0;
  1093.             v=add_var(empty,t2,AUTO,0);
  1094.             new=mymalloc(ICS);
  1095.             new->code=ASSIGN;
  1096.             new->typf=t;
  1097.             new->q1=*arg;
  1098.             new->q2.flags=0;
  1099.             new->q2.val.vlong=sizetab[t&NQ];
  1100.             new->z.flags=VAR;
  1101.             new->z.v=v;
  1102.             new->z.val.vlong=l2zl(0L);
  1103.             add_IC(new);
  1104.             nrl=mymalloc(sizeof(*nrl));
  1105.             nrl->next=*rl;
  1106.             nrl->reg=reg;
  1107.             nrl->v=v;
  1108.             *rl=nrl;
  1109. #ifdef HAVE_REGPARMS
  1110.             if(radr||rreg==-1)
  1111. #else
  1112.             if(n==0)
  1113. #endif
  1114.             {
  1115.             /*  Letztes Argument; jetzt in Register laden.  */
  1116.                 for(;nrl;nrl=nrl->next){
  1117.                     new=mymalloc(ICS);
  1118.                     new->code=ASSIGN;
  1119.                     new->typf=nrl->v->vtyp->flags|VOLATILE;
  1120.                     new->q1.flags=VAR;
  1121.                     new->q1.v=nrl->v;
  1122.                     new->q1.val.vlong=l2zl(0L);
  1123.                     new->q2.flags=0;
  1124.                     new->q2.val.vlong=szof(nrl->v->vtyp);
  1125.                     new->z.flags=VAR;
  1126.                     new->z.val.vlong=l2zl(0L);
  1127.                     new->z.v=add_var(empty,clone_typ(nrl->v->vtyp),AUTO,0);
  1128.                     new->z.v->reg=nrl->reg;
  1129.                     nrl->v=new->z.v;
  1130.                     add_IC(new);
  1131.                 }
  1132.             }
  1133.             return(of);
  1134.         }else{
  1135.         /*  Nicht-optimierende Version. */
  1136.             if(!regs[reg]){
  1137.                 new=mymalloc(ICS);
  1138.                 new->code=ALLOCREG;
  1139.                 new->typf=0;
  1140.                 new->q1.flags=REG;
  1141.                 new->q1.reg=reg;
  1142.                 new->q2.flags=new->z.flags=0;
  1143.                 add_IC(new);
  1144.                 regs[reg]=33;regused[reg]++;
  1145.             }else{
  1146.                 if(arg->flags!=(REG|SCRATCH)||arg->reg!=reg){
  1147.                     t2=clone_typ(regtype[reg]);
  1148.                     v=add_var(empty,t2,AUTO,0);
  1149.                     v->flags|=USEDASADR;
  1150.                     new=mymalloc(ICS);
  1151.                     new->code=MOVEFROMREG;
  1152.                     new->typf=0;
  1153.                     new->q1.flags=REG;
  1154.                     new->q1.reg=reg;
  1155.                     new->q2.flags=0;
  1156.                     new->q2.val.vlong=regsize[reg];
  1157.                     new->z.flags=VAR|DONTREGISTERIZE;
  1158.                     new->z.v=v;
  1159.                     new->z.val.vlong=l2zl(0L);
  1160.                     add_IC(new);
  1161.                 }else regs[reg]|=32;
  1162.             }
  1163.             new=mymalloc(ICS);
  1164.             new->code=ASSIGN;
  1165.             new->typf=t;
  1166.             new->q1=*arg;
  1167.             new->q2.flags=new->z.flags=0;
  1168.             new->q2.val.vlong=sizetab[t&NQ];
  1169.             new->z.flags=REG;
  1170.             new->z.reg=reg;
  1171.             add_IC(new);
  1172.             nrl=mymalloc(sizeof(*nrl));
  1173.             nrl->next=*rl;
  1174.             nrl->reg=reg;
  1175.             nrl->v=v;
  1176.             *rl=nrl;
  1177.             return(of);
  1178.         }
  1179.     }
  1180. }
  1181.  
  1182. void convert(np p,int f)
  1183. /*  konvertiert das Objekt in p->o in bestimmten Typ    */
  1184. {
  1185.     struct IC *new;
  1186.     if((f&NQ)==VOID||(p->ntyp->flags&NU)==f) return;
  1187.     if(p->flags==CEXPR||p->flags==PCEXPR){
  1188.         eval_constn(p);
  1189.         p->ntyp->flags=f;
  1190.         insert_const(p);
  1191.         p->o.val=p->val;
  1192.         return;
  1193.     }
  1194.     if(!must_convert(p,f)) return;
  1195.     new=mymalloc(ICS);
  1196.     new->q1=p->o;
  1197.     new->q2.flags=0;
  1198.     new->code=CONVCHAR+(p->ntyp->flags&NQ)-CHAR;
  1199.     if(p->ntyp->flags&UNSIGNED) new->code+=8;
  1200.     new->typf=f;
  1201.     if(!regok(p->o.reg,f,0)||!(p->o.flags&SCRATCH)){
  1202.         get_scratch(&new->z,f,0,0);
  1203.         p->o=new->z;
  1204.         add_IC(new);
  1205.     }else{
  1206.         new->z=p->o;new->z.flags&=~DREFOBJ;
  1207.         p->o=new->z;
  1208.         add_IC(new);
  1209.     }
  1210. }
  1211.  
  1212. int allocreg(int f,int mode)
  1213. /*  Fordert Register fuer Typ f an                      */
  1214. /*  evtl. maschinenabhaengig, aber hier fehlt noch viel */
  1215. /*  z.B. Eintragen eines IC                             */
  1216. {
  1217.     int i;struct IC *new;
  1218.     if(nocode) return(1);
  1219.     for(i=1;i<=MAXR;i++){
  1220.         if(!regs[i]&®ok(i,f,mode)){
  1221.             if(DEBUG&16) printf("alocated %s\n",regnames[i]);
  1222.             regs[i]=1;regused[i]++;
  1223.             new=mymalloc(ICS);
  1224.             new->code=ALLOCREG;
  1225.             new->typf=0;
  1226.             new->q1.flags=REG;
  1227.             new->q1.reg=i;
  1228.             new->q2.flags=new->z.flags=0;
  1229.             add_IC(new);
  1230.             return(i);
  1231.         }
  1232.     }
  1233.     if(DEBUG&1) printf(">%sCouldn't allocate register for type %d\n",string,f);
  1234.     return(0);
  1235. }
  1236. void free_reg(int r)
  1237. /*  Gibt Register r frei                                */
  1238. /*  Eintrag eines IC fehlt noch                         */
  1239. {
  1240.     struct IC *new;
  1241.     if(!r||nocode) return;
  1242.     if(regs[r]==0) {printf("Register %d(%s):\n",r,regnames[r]);ierror(0);}
  1243.     if(DEBUG&16) printf("freed %s\n",regnames[r]);
  1244.     new=mymalloc(ICS);
  1245.     new->code=FREEREG;
  1246.     new->typf=0;
  1247.     new->q1.flags=REG;
  1248.     new->q1.reg=r;
  1249.     new->q2.flags=new->z.flags=0;
  1250.     add_IC(new);
  1251.     regs[r]=0;
  1252. }
  1253. void gen_label(int l)
  1254. /*  Erzeugt ein Label                                   */
  1255. {
  1256.     struct IC *new;
  1257.     new=mymalloc(ICS);
  1258.     new->code=LABEL;
  1259.     new->typf=l;
  1260.     new->q1.flags=new->q2.flags=new->z.flags=0;
  1261.     add_IC(new);
  1262. }
  1263. void gen_cond(struct obj *p,int m,int l1,int l2)
  1264. /*  Generiert code, der 0 oder 1 in Register schreibt. Schreibt obj nach p. */
  1265. {
  1266.     struct IC *new;
  1267.     struct obj omerk;
  1268.     new=mymalloc(ICS);
  1269.     new->code=ASSIGN;
  1270.     new->typf=INT;
  1271.     new->q1.flags=KONST;
  1272.     new->q2.flags=0;
  1273.     new->q2.val.vlong=sizetab[INT];
  1274.     if(!m) vlong=l2zl(1L); else vlong=l2zl(0L);
  1275.     new->q1.val.vint=zl2zi(vlong);
  1276.     get_scratch(&new->z,INT,0,0);
  1277.     omerk=new->z;
  1278.     add_IC(new);
  1279.     new=mymalloc(ICS);
  1280.     new->code=BRA;
  1281.     new->typf=l2;
  1282.     add_IC(new);
  1283.     gen_label(l1);
  1284.     new=mymalloc(ICS);
  1285.     new->code=ASSIGN;
  1286.     new->typf=INT;
  1287.     new->q1.flags=KONST;
  1288.     new->q2.flags=0;
  1289.     new->q2.val.vlong=sizetab[INT];
  1290.     if(!m) vlong=l2zl(0L); else vlong=l2zl(1L);
  1291.     new->q1.val.vint=zl2zi(vlong);
  1292.     new->z=omerk;
  1293. /*    new->z.reg=r;
  1294.     new->z.flags=SCRATCH|REG;*/
  1295.     add_IC(new);
  1296.     gen_label(l2);
  1297.     *p=omerk;
  1298. }
  1299. void scratch_var(struct obj *o,int t,struct Typ *typ)
  1300. /*  liefert eine temporaere Variable                            */
  1301. /*  nicht effizient, aber wer hat schon so wenig Register...    */
  1302. {
  1303.   struct Typ *nt;
  1304.   if((t&NQ)<CHAR||(t&NQ)>POINTER){
  1305.     if(!typ) ierror(0);
  1306.     nt=clone_typ(typ);
  1307.   }else{
  1308.     nt=mymalloc(TYPS);
  1309.     nt->flags=t&NU;
  1310.     if((t&NQ)==POINTER){
  1311.       nt->next=mymalloc(TYPS);
  1312.       nt->next->flags=VOID;
  1313.       nt->next->next=0;
  1314.     }else nt->next=0;
  1315.   }
  1316.   o->flags=SCRATCH|VAR;o->reg=0;
  1317.   o->v=add_var(empty,nt,AUTO,0);
  1318.   o->val.vlong=l2zl(0L);
  1319. }
  1320. void get_scratch(struct obj *o,int t1,int t2,struct Typ *typ)
  1321. /*  liefert ein Scratchregister oder eine Scratchvariable       */
  1322. {
  1323.     if(!(optflags&2)&&(o->reg=allocreg(t1,t2))){
  1324.         o->flags=SCRATCH|REG;
  1325.     }else{
  1326.         scratch_var(o,t1,typ);
  1327.     }
  1328. }
  1329. int do_arith(np p,struct IC *new,np dest,struct obj *o)
  1330. /*  erzeugt IC new fuer einen arithmetischen Knoten und speichert das   */
  1331. /*  Resultat vom Unterknoten dest in o (fuer a op= b)               */
  1332. /*  liefert 0, wenn dest nicht gefunden                             */
  1333. {
  1334.     int f=0,mflags;
  1335.     new->code=p->flags;
  1336.     if(new->code==PMULT) new->code=MULT;
  1337.     gen_IC(p->left,0,0);
  1338.     if(dest&&p->left==dest) {*o=p->left->o;f++;}
  1339.     gen_IC(p->right,0,0);
  1340.     if(dest&&p->right==dest) {*o=p->right->o;f++;}
  1341.     if(dest){ mflags=dest->o.flags;dest->o.flags&=(~SCRATCH);}
  1342.  
  1343.     if((p->left->ntyp->flags&NQ)==POINTER&&(p->right->ntyp->flags&NQ)==POINTER){
  1344.     /*  Subtrahieren zweier Pointer                                 */
  1345.         if(p->flags!=SUB) ierror(0);
  1346.         new->typf=INT;
  1347.         new->code=SUBPFP;
  1348.         new->q1=p->left->o;
  1349.         new->q2=p->right->o;
  1350.         if(!dest&&(p->left->o.flags&SCRATCH)&®ok(p->left->o.reg,INT,0)){
  1351.             new->z=p->left->o;
  1352.             new->z.flags&=~DREFOBJ;
  1353.         }else{
  1354.             if(USEQ2ASZ&&(p->right->o.flags&SCRATCH)&®ok(p->right->o.reg,INT,0)){
  1355.                 new->z=p->right->o;
  1356.                 new->z.flags&=(~DREFOBJ);
  1357.             }else{
  1358.                 get_scratch(&new->z,INT,0,0);
  1359.             }
  1360.         }
  1361.         p->o=new->z;
  1362.         add_IC(new);
  1363.         if(!zlleq(szof(p->left->ntyp->next),l2zl(1L))){
  1364.             new=mymalloc(ICS);
  1365.             new->code=DIV;
  1366.             new->q1=p->o;
  1367.             new->q2.flags=KONST;
  1368.             vlong=szof(p->left->ntyp->next);
  1369.             vint=zl2zi(vlong);
  1370.             new->q2.val.vint=vint;
  1371.             new->z=p->o;
  1372.             new->typf=INT;
  1373.             add_IC(new);
  1374.         }
  1375.         if(dest) dest->o.flags=mflags;
  1376.         return(f);
  1377.     }
  1378.     if((p->flags==ADD||p->flags==SUB)&&(p->ntyp->flags&NQ)==POINTER){
  1379.     /*  Addieren und Subtrahieren eines Integers zu einem Pointer   */
  1380.         if(p->flags==ADD) new->code=ADDI2P; else new->code=SUBIFP;
  1381.         new->typf=p->right->ntyp->flags&NU;
  1382.         new->q1=p->left->o;
  1383.         /*  kleinere Typen als MINADDI2P erst in diesen wandeln */
  1384.         if((new->typf&NQ)<MINADDI2P){convert(p->right,/*UNSIGNED|*/MINADDI2P);new->typf=/*UNSIGNED|*/MINADDI2P;}
  1385.         new->q2=p->right->o;
  1386.         if(!dest&&(p->left->o.flags&SCRATCH)&®ok(new->q1.reg,POINTER,p->left->ntyp->next->flags&NU)){
  1387.             new->z=p->left->o;
  1388.             new->z.flags&=(~DREFOBJ);
  1389.         }else{
  1390.             get_scratch(&new->z,POINTER,p->left->ntyp->next->flags&NU,0);
  1391.         }
  1392.         p->o=new->z;
  1393.         add_IC(new);
  1394.         if(dest) dest->o.flags=mflags;
  1395.         return(f);
  1396.     }
  1397.     convert(p->left,p->ntyp->flags&NU);
  1398.     convert(p->right,p->ntyp->flags&NU);
  1399.     new->q1=p->left->o;
  1400.     new->q2=p->right->o;
  1401.     new->typf=p->ntyp->flags&NU;
  1402.     /*  Bei dest!=0, d.h. ASSIGNADD, darf q1 nicht als Ziel benuzt werden!  */
  1403.     if(!dest&&(new->q1.flags&SCRATCH)&®ok(new->q1.reg,p->ntyp->flags,0)){
  1404.         new->z=new->q1;
  1405.         new->z.flags&=~DREFOBJ;
  1406.     }else{
  1407.         if((new->q2.flags&SCRATCH)&®ok(new->q2.reg,p->ntyp->flags,0)){
  1408.             if((p->flags>=OR&&p->flags<=AND)||p->flags==ADD||p->flags==MULT||p->flags==PMULT){
  1409.             /*  bei kommutativen Operatoren vertauschen     */
  1410.                 new->z=new->q2;
  1411.                 new->q2=new->q1;
  1412.                 new->q1=new->z;
  1413.                 new->z.flags&=~DREFOBJ;
  1414.             }else{
  1415.                 if(USEQ2ASZ){
  1416.                     new->z=new->q2;
  1417.                     new->z.flags&=~DREFOBJ;
  1418.                 }else{
  1419.                     get_scratch(&new->z,new->typf,0,0);
  1420.                 }
  1421.             }
  1422.         }else{
  1423.             get_scratch(&new->z,new->typf,0,0);
  1424.         }
  1425.     }
  1426.     p->o=new->z;
  1427.     add_IC(new);
  1428.     if(dest) dest->o.flags=mflags;
  1429.     return(f);
  1430. }
  1431. void savescratch(int code,struct IC *p,int dontsave)
  1432. /*  speichert Scratchregister bzw. stellt sie wieder her (je nach code  */
  1433. /*  entweder MOVEFROMREG oder MOVETOREG)                                */
  1434. {
  1435.     int i,s,e,b;struct IC *new;
  1436.     if(code==MOVETOREG){ s=1;e=MAXR+1;b=1;} else {s=MAXR;e=0;b=-1;}
  1437.     for(i=s;i!=e;i+=b){
  1438.         if(regs[i]&&!(regs[i]&32)&®scratch[i]&&i!=dontsave){
  1439.             if(!regsbuf[i]){
  1440.                 struct Typ *t;
  1441.                 if(code!=MOVEFROMREG) continue;
  1442.                 t=clone_typ(regtype[i]);
  1443.                 regsbuf[i]=add_var(empty,t,AUTO,0);
  1444.                 regsbuf[i]->flags|=USEDASADR;
  1445.                 regbnesting[i]=nesting;
  1446.             }
  1447.             new=mymalloc(ICS);
  1448.             new->typf=new->q2.flags=0;
  1449.             new->line=0;new->file=0;
  1450.             new->code=code;
  1451.             if(code==MOVEFROMREG){
  1452.                 new->q1.flags=REG;new->q1.reg=i;
  1453.                 new->z.flags=VAR|DONTREGISTERIZE;new->z.v=regsbuf[i];
  1454.                 new->z.val.vlong=l2zl(0L);
  1455.             }else{
  1456.                 new->z.flags=REG;new->z.reg=i;
  1457.                 new->q1.flags=VAR|DONTREGISTERIZE;new->q1.v=regsbuf[i];
  1458.                 new->q1.val.vlong=l2zl(0L);
  1459.             }
  1460.             new->use_cnt=new->change_cnt=0;
  1461.             new->use_list=new->change_list=0;
  1462.             insert_IC(p,new);
  1463.         }
  1464.     }
  1465. }
  1466.  
  1467.